package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.wordmemorize.converter.ReviewConverter;
import com.cskaoyan.wordmemorize.dao.entity.UserCheckinStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserRevStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocRevDO;
import com.cskaoyan.wordmemorize.dao.entity.VocDO;
import com.cskaoyan.wordmemorize.dao.mapper.UserCheckinStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserRevStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocRevMapper;
import com.cskaoyan.wordmemorize.dao.mapper.VocMapper;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.DownLoadUserReviewDTO;
import com.cskaoyan.wordmemorize.dto.app.UserReviewStatisticsDTO;
import com.cskaoyan.wordmemorize.dto.app.UserVocRevDTO;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserReviewDataCommand;
import com.cskaoyan.wordmemorize.request.UserReviewStatisticsCommand;
import com.cskaoyan.wordmemorize.request.UserVocRevCommand;
import com.cskaoyan.wordmemorize.service.UserReviewService;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class UserReviewServiceImpl extends ServiceImpl<UserVocRevMapper, UserVocRevDO> implements UserReviewService {

    @Autowired
    UserVocRevMapper userVocRevMapper;
    @Autowired
    ReviewConverter reviewConverter;//转换器
    @Autowired
    UserRevStatisticsMapper userRevStatisticsMapper;
    @Autowired
    UserCheckinStatisticsMapper userCheckinStatisticsMapper;
    // 上传APP段复习数据
    @Override
    public void synchronizeUserReviewData(UserReviewDataCommand command, Long userId) {
        // 1. 处理复习统计数据
        if (command.getRevStatisticsCommand() != null) {
            processReviewStatistics(command.getRevStatisticsCommand(), userId);
        }

        // 2. 处理单词复习数据
        if (command.getVocRevCommands() != null && !command.getVocRevCommands().isEmpty()) {
            processVocReviewData(command.getVocRevCommands(), userId);
        }
    }

    // APP端下载复习数据(首次登录时)
    @Override
    public DownLoadUserReviewDTO downloadUserReviewData(PageRequest pageRequest, Long userId) {
        DownLoadUserReviewDTO result = new DownLoadUserReviewDTO();

        // 设置分页参数
        int pageNum = pageRequest.getPageNum() == null ? 1 : pageRequest.getPageNum();
        int pageSize = pageRequest.getCount() == null ? 10 : pageRequest.getCount();

        // 1. 分页查询用户单词复习数据
        Page<UserVocRevDO> vocRevPage = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<UserVocRevDO> vocRevQuery = new LambdaQueryWrapper<>();
        vocRevQuery.eq(UserVocRevDO::getUserId, userId);
        Page<UserVocRevDO> vocRevDOPage = userVocRevMapper.selectPage(vocRevPage, vocRevQuery);

        // 使用转换器进行转换
        PageDTO<UserVocRevDTO> vocRevDTOPage = reviewConverter.userVocRevPage2PageDTO(
                vocRevDOPage.getRecords(),
                vocRevDOPage.getTotal()
        );

        // 2. 分页查询用户复习统计数据
        Page<UserRevStatisticsDO> statisticsPage = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<UserRevStatisticsDO> statisticsQuery = new LambdaQueryWrapper<>();
        statisticsQuery.eq(UserRevStatisticsDO::getUserId, userId)
                .orderByDesc(UserRevStatisticsDO::getReviewDate);
        Page<UserRevStatisticsDO> statisticsDOPage = userRevStatisticsMapper.selectPage(statisticsPage, statisticsQuery);

        // 使用转换器进行转换
        PageDTO<UserReviewStatisticsDTO> statisticsDTOPage = reviewConverter.userRevStatistcsPage2PageDTO(
                statisticsDOPage.getRecords(),
                statisticsDOPage.getTotal()
        );

        // 3. 组装结果
        result.setUserVocRevPage(vocRevDTOPage);
        result.setUserReviewStatisticsPage(statisticsDTOPage);

        return result;
    }

    // APP端添加复习单词
    @Override
    @Transactional
    public void addUserRovRev(List<Long> vocIds, Long userId) {
        if (CollectionUtils.isEmpty(vocIds)){
            return;
        }
        // 1. 查询已存在的复习记录
        List<UserVocRevDO> existingRecords = userVocRevMapper.selectList(
                new LambdaQueryWrapper<UserVocRevDO>()
                        .eq(UserVocRevDO::getUserId, userId)
                        .in(UserVocRevDO::getVocId, vocIds)
        );

        // 2. 获取已存在的单词ID集合
        Set<Long> existingVocIds = existingRecords.stream()
                .map(UserVocRevDO::getVocId)
                .collect(Collectors.toSet());

        // 3. 过滤出需要新增的单词ID
        List<UserVocRevDO> newRecords = vocIds.stream()
                .filter(vocId -> !existingVocIds.contains(vocId))
                .map(vocId -> createInitialReviewRecord(vocId, userId))
                .collect(Collectors.toList());

        // 4. 批量保存
        if (!CollectionUtils.isEmpty(newRecords)) {
            saveBatch(newRecords);
        }
    }

    private UserVocRevDO createInitialReviewRecord(Long vocId, Long userId) {
        UserVocRevDO record = new UserVocRevDO();
        record.setVocId(vocId);
        record.setUserId(userId);
        // 初始易度因子（默认值1.5）
        record.setFactor(1.5);
        // 初始复习间隔（0表示还未学习）
        record.setReviewInterval(0);
        // 初始复习状态：0=已选未学
        record.setType(0);
        // 初始熟悉度：0=不认识
        record.setFamiliarity(0);
        // 连续失败次数初始为0
        record.setConsecutiveFailCount(0);
        // 总复习次数初始为0
        record.setTotalReview(0);
        // 初始无下次复习日期（学习后才设置）
        record.setNextReviewDate(null);
        return record;
    }


    private void processReviewStatistics(UserReviewStatisticsCommand command, Long userId) {
        // 转换为DO对象
        UserRevStatisticsDO statisticsDO = reviewConverter.userRevStatisticsCommand2DO(command);
        statisticsDO.setUserId(userId);

        // 查询是否已存在当天的复习统计数据
        LambdaQueryWrapper<UserRevStatisticsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRevStatisticsDO::getUserId, userId)
                .eq(UserRevStatisticsDO::getReviewDate, command.getReviewDate());

        UserRevStatisticsDO existing = userRevStatisticsMapper.selectOne(queryWrapper);

        if (existing != null) {
            // 计算学习时间增量（毫秒）
            long timeIncrement = parseStudyTime(command.getStudyTime())
                    - parseStudyTime(String.valueOf(existing.getStudyTime()));

            // 更新现有记录
            statisticsDO.setId(existing.getId());
            userRevStatisticsMapper.updateById(statisticsDO);

            // 更新总学习时间
            if (timeIncrement > 0) {
                updateTotalStudyTime(userId, timeIncrement);
            }
        } else {
            // 插入新记录
            userRevStatisticsMapper.insert(statisticsDO);

            // 更新总学习时间
            long timeIncrement = parseStudyTime(command.getStudyTime());
            if (timeIncrement > 0) {
                updateTotalStudyTime(userId, timeIncrement);
            }
        }
    }

    private void processVocReviewData(List<UserVocRevCommand> commands, Long userId) {
        // 转换为DO对象列表
        List<UserVocRevDO> reviewDOs = reviewConverter.userVocRevCommands2DOs(commands);

        // 确保用户ID正确
        reviewDOs.forEach(doItem -> doItem.setUserId(userId));

        // 分批更新
        List<List<UserVocRevDO>> batches = Lists.partition(reviewDOs, 500);
        for (List<UserVocRevDO> batch : batches) {
            for (UserVocRevDO record : batch) {
                // 使用 MyBatis-Plus 的 saveOrUpdate 方法
                LambdaUpdateWrapper<UserVocRevDO> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(UserVocRevDO::getId, record.getId());

                userVocRevMapper.update(record, updateWrapper);
            }
        }
    }

    private void updateTotalStudyTime(Long userId, long timeIncrement) {
        // 查询用户统计数据
        LambdaQueryWrapper<UserCheckinStatisticsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserCheckinStatisticsDO::getUserId, userId);

        UserCheckinStatisticsDO stats = userCheckinStatisticsMapper.selectOne(queryWrapper);

        if (stats != null) {
            // 更新总学习时间
            stats.setTotalTime(stats.getTotalTime() + timeIncrement);
            userCheckinStatisticsMapper.updateById(stats);
        } else {
            // 创建新记录
            UserCheckinStatisticsDO newStats = new UserCheckinStatisticsDO();
            newStats.setUserId(userId);
            newStats.setTotalTime(timeIncrement);
            userCheckinStatisticsMapper.insert(newStats);
        }
    }
    // 将学习时间字符串解析为毫秒数
    private long parseStudyTime(String studyTime) {
        if (studyTime == null || studyTime.isEmpty()) {
            return 0;
        }

        try {
            // 尝试解析为毫秒数值
            return Long.parseLong(studyTime);
        } catch (NumberFormatException e) {
            // 尝试解析为时间格式 (HH:mm:ss)
            try {
                String[] parts = studyTime.split(":");
                long hours = Long.parseLong(parts[0]);
                long minutes = parts.length > 1 ? Long.parseLong(parts[1]) : 0;
                long seconds = parts.length > 2 ? Long.parseLong(parts[2]) : 0;

                return (hours * 3600 + minutes * 60 + seconds) * 1000;
            } catch (Exception ex) {
                return 0;
            }
        }
    }
}
